﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using SegIdenPC.Entidad;
using SegIdenPC.Herramientas;
using log4net;
using GS1.Utilitario;
using System.Drawing.Imaging;
using System.Configuration;

namespace SegIdenPC.Formularios
{
    public partial class frmMantProducto : Form
    {
        #region --- Variables y Propiedades ---
        private static readonly ILog log = LogManager.GetLogger(typeof(frmMantProducto));

        private const string LLAVE_RUTAIMAGEN = "RUTAIMAGEN";
        
        private const string TITULO = "Mantenimiento de Productos";
        private const string FORMATO_TOTAL_ENCONTRADOS = "Total productos encontrados: {0}";

        private const string FILTRO_VENTANA_EXAMINAR = "Archivos Imagen (*.jpg)|*.jpg";
        private const string TITULO_EXAMINAR_ARCHIVO_IMAGEN = "Seleccione su archivo de Imagen";
        private string RUTA_INICIAL = ConfigurationManager.AppSettings[LLAVE_RUTAIMAGEN];

        private string ESTADO = string.Empty;

        public enum OperacionMantenimiento
        {
            Nuevo,
            Editar
        }

        private OperacionMantenimiento tipoOperacion = OperacionMantenimiento.Nuevo;

        private enum Opcion
        {
            Abrir = 0,
            Nuevo = 1,
            Editar = 2,
            Grabar = 3,
            Cancelar = 4,
            Eliminar = 5
        }

        public Producto productoActual { get; set; }

        private Proveedor proveedorActual = null;

        private Nivel niveles = null;

        public bool formularioBusqueda { get; set; }

        private ListaComponente listaComponente = null;

        #endregion

        #region --- Constructor ---
        public frmMantProducto()
        {
            InitializeComponent();
        }
        #endregion

        #region --- Eventos Formulario ---
        private void frmMantProducto_Load(object sender, EventArgs e)
        {
            cargarFormulario();
        }
        
        private void frmMantProducto_FormClosing(object sender, FormClosingEventArgs e)
        {
            finalizarFormulario();
        }

        private void tbtnAbrir_Click(object sender, EventArgs e)
        {
            abrir();
        }

        private void tbtnNuevo_Click(object sender, EventArgs e)
        {
            nuevo();
        }

        private void tbtnEditar_Click(object sender, EventArgs e)
        {
            editar();
        }

        private void tbtnGrabar_Click(object sender, EventArgs e)
        {
            grabar();
        }

        private void tbtnCancelar_Click(object sender, EventArgs e)
        {
            cancelar();
        }

        private void tbtnEliminar_Click(object sender, EventArgs e)
        {
            eliminar();
        }

        private void btnBuscar_Click(object sender, EventArgs e)
        {
            buscar();
        }

        private void tbtnSalir_Click(object sender, EventArgs e)
        {
            salir();
        }

        private void tabControl_Selecting(object sender, TabControlCancelEventArgs e)
        {
            if (!e.TabPage.Enabled) { e.Cancel = true; }
        }

        private void btnBuscarProveedor_Click(object sender, EventArgs e)
        {
            elegirProveedor();
        }

        private void btnRutaImagen_Click(object sender, EventArgs e)
        {
            buscarImagen();
        }

        private void txtCampoDecimal_KeyPress(object sender, KeyPressEventArgs e)
        {
            Libreria.SoloNumeros((TextBox)sender, e, true, 2);
        }

        private void cboNivelProducto_SelectedIndexChanged(object sender, EventArgs e)
        {
            seleccionNiveles();
        }

        private void cboCriterioNivelProducto_SelectedIndexChanged(object sender, EventArgs e)
        {
            seleccionNivelesBusqueda();
        }

        private void chkComponentes_CheckedChanged(object sender, EventArgs e)
        {
            this.btnComponentes.Enabled = this.chkComponentes.Checked;
        }

        private void dgvListado_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
        {
            seleccionarProducto();
        }

        private void txtCriterioCodProductoProv_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter) { buscar(); }
        }

        private void tbtn_retorno_Click(object sender, EventArgs e)
        {
            retorno(); 
        }

        private void btnComponentes_Click(object sender, EventArgs e)
        {
            abrirComponentes();
        }

        #endregion

        #region --- Metodos Propios ---
        private void retorno()
        {
            //revisar
            if ((this.tipoOperacion == OperacionMantenimiento.Editar) ||
               (!this.grpDatos.Enabled))
            {
                this.cboCriterioNivelProducto.SelectedValue = Constantes.CODIGO_SELECCIONE;
                this.cboCriterioNivelTipo.SelectedValue = Constantes.CODIGO_SELECCIONE;
                this.cboCriterioNivelMaterial.SelectedValue = Constantes.CODIGO_SELECCIONE;
                this.cboCriterioNivelColor.SelectedValue = Constantes.CODIGO_SELECCIONE;

                this.txtCriterioCodProductoProv.Text = this.txtCodProductoProv.Text;

                // Refrescar grilla
                listarProductos();
            }

            // Estableciendo estado de TagPage de Listado y datos
            this.tabPagListado.Enabled = true; this.tabPagDatos.Enabled = false;

            // Mostrar la primera pagina del TabControl
            this.tabControl.SelectedIndex = 0;

            // Deshabilitando el grupoBox de datos
            this.grpDatos.Enabled = false;

            // Estableciendo los estados de los botones
            cambiarEstadoBotones(Opcion.Cancelar);

            // Estableciendo focus
            this.btnBuscar.Focus();
        }

        private void cargarFormulario()
        {
            ListaGeneral listaEstado = null;

            try
            {
                Cursor.Current = Cursors.WaitCursor;

                // Activaciones de botones por rol
                controlBotonesPorRol();

                // Instanciando y creando listado de estado
                listaEstado = new ListaGeneral();
                listaEstado.Add(new General { codigo = Constantes.ESTADO_CODIGO_ACTIVO, descripcion = Constantes.ESTADO_DESCRIPCION_ACTIVO });
                listaEstado.Add(new General { codigo = Constantes.ESTADO_CODIGO_INACTIVO, descripcion = Constantes.ESTADO_DESCRIPCION_INACTIVO });

                // Desactivando el grupo de campo de informacion
                this.tabPagDatos.Enabled = false;

                // Estableciendo Ficha 0 como seleccion incial
                this.tabControl.SelectedIndex = 0;
                // Capturando evento selecting en el control Tab
                this.tabControl.Selecting += new TabControlCancelEventHandler(tabControl_Selecting);

                // Estableciendo a 0 el texto del total de registros encontrados.
                this.lblTotalRegistros.Text = string.Format(FORMATO_TOTAL_ENCONTRADOS, 0);

                // Desactivando el boton abrir.
                this.tbtnAbrir.Enabled = false;

                // Estableciendo datos del combo Estado
                this.cboEstado.DataSource = listaEstado;
                this.cboEstado.ValueMember = Constantes.GENERAL_CODIGO;
                this.cboEstado.DisplayMember = Constantes.GENERAL_DESCRIPCION;
                this.cboEstado.SelectedIndex = 0;

                // Ejecutar carga del combo Niveles
                cargarNiveles();

                this.listaComponente = new ListaComponente();

                // Estableciendo focus
                this.btnBuscar.Focus();

            }
            catch (Exception ex)
            {
                log.Error(ex.Message, ex);
                Libreria.MensajeError(ex, TITULO);
            }
            finally
            {
                Cursor.Current = Cursors.Default;
            }
        }

        private void cargarNiveles()
        {
            Operacion operacion = null;
            string contenidoXML = string.Empty;

            // Estableciendo operacion a ser enviada al Servicio REST
            operacion = new Operacion();
            operacion.numero = Constantes.OPERACION_LISTAR_NIVELES;

            // Instanciando y ejecutando llamada al ServicioREST
            ConexionREST conexionREST = new ConexionREST();
            contenidoXML = conexionREST.ejecutarOperacion(operacion);

            // Obteniendo Objeto de Error
            OperacionError operacionError = contenidoXML.DeserializarTo<OperacionError>();

            // Validar si hay error
            if (operacionError != null)
            {
                Libreria.ShowMessageboxError(operacionError.descripcion);
                return;
            }

            // Obteniendo Objeto de Nivel
            this.niveles = contenidoXML.DeserializarTo<Nivel>();

            // Estableciendo listado de nivel de producto
            this.cboNivelProducto.DataSource = this.niveles.listaNivelProducto.lista;
            this.cboNivelProducto.ValueMember = Constantes.GENERAL_CODIGO;
            this.cboNivelProducto.DisplayMember = Constantes.GENERAL_DESCRIPCION;
            this.cboNivelProducto.SelectedIndex = 0;

            // Creando listado para nivel de producto para busqueda
            ListaNivelProducto listaNivelProducto = new ListaNivelProducto();
            listaNivelProducto.add(new NivelProducto { codigo = Constantes.CODIGO_SELECCIONE, descripcion = Constantes.DESCRIPCION_SELECCIONE });

            foreach (NivelProducto nivelProducto in this.niveles.listaNivelProducto.lista)
            {
                listaNivelProducto.add(new NivelProducto { codigo = nivelProducto.codigo, descripcion = nivelProducto.descripcion });
            }

            // Estableciendo listado de nivel de producto para busqueda
            this.cboCriterioNivelProducto.DataSource = listaNivelProducto.lista;
            this.cboCriterioNivelProducto.ValueMember = Constantes.GENERAL_CODIGO;
            this.cboCriterioNivelProducto.DisplayMember = Constantes.GENERAL_DESCRIPCION;
            this.cboCriterioNivelProducto.SelectedIndex = 0;
        }

        private void finalizarFormulario()
        {
            this.tabControl.Selecting -= new TabControlCancelEventHandler(tabControl_Selecting);
        }

        private void pintarGrilla()
        {
            ListPersonalizada<Producto> listaProductos = null;
            listaProductos = (ListPersonalizada<Producto>)this.dgvListado.DataSource;

            if (listaProductos != null)
            {
                for (int i = 0; i < listaProductos.Count; i++)
                {
                    var producto = listaProductos[i];

                    producto.estado = producto.estado.Equals(Constantes.ESTADO_CODIGO_INACTIVO) ? Constantes.ESTADO_DESCRIPCION_INACTIVO : Constantes.ESTADO_DESCRIPCION_ACTIVO;

                    if (producto.estado == Constantes.ESTADO_DESCRIPCION_INACTIVO)
                    {
                        this.dgvListado.Rows[i].DefaultCellStyle.BackColor = Color.FromArgb(255, 128, 128);
                    }
                }
            }
        }

        private bool validarEntradaBusqueda()
        {
            this.txtCriterioCodProductoProv.Text = this.txtCriterioCodProductoProv.Text.Trim();

            if (this.cboCriterioNivelProducto.SelectedValue.ToString().Equals(Constantes.CODIGO_SELECCIONE) &&
                  this.txtCriterioCodProductoProv.Text.Equals(string.Empty)&&
                  this.txtDescripcionBusqueda.Text.Equals(string.Empty))
            {
                Libreria.CampoNecesario(this.cboCriterioNivelProducto, "Debe ingresar o selecionar los filtros de busqueda");
                return true;
            }

            if (!this.txtCriterioCodProductoProv.Text.Equals(string.Empty) &&
                  this.txtCriterioCodProductoProv.TextLength < 3)
            {
                Libreria.CampoNecesario(this.txtCriterioCodProductoProv, "Debe ingresar por lo menos 3 caracteres para realizar la busqueda");
                return true;
            }

            return false;
        }

        private void listarProductos()
        {
            Operacion operacion = null;
            string contenidoXML = string.Empty;

            // Estableciendo operacion a ser enviada al Servicio REST
            operacion = new Operacion();
            operacion.numero = Constantes.OPERACION_LISTAR_PRODUCTOS;

            operacion.producto = new Producto();

            operacion.producto.nivelProducto = new NivelProducto();
            operacion.producto.nivelProducto.codigo = this.cboCriterioNivelProducto.SelectedValue.ToString().Equals(Constantes.CODIGO_SELECCIONE) ?
                                                                    Constantes.VALOR_CERO :
                                                                    this.cboCriterioNivelProducto.SelectedValue.ToString();

            operacion.producto.nivelTipo = new NivelTipo();
            operacion.producto.nivelTipo.codigo = this.cboCriterioNivelTipo.SelectedValue.ToString().Equals(Constantes.CODIGO_SELECCIONE) ?
                                                                    Constantes.VALOR_CERO : 
                                                                    this.cboCriterioNivelTipo.SelectedValue.ToString();

            operacion.producto.nivelMaterial = new NivelMaterial();
            operacion.producto.nivelMaterial.codigo = this.cboCriterioNivelMaterial.SelectedValue.ToString().Equals(Constantes.CODIGO_SELECCIONE) ?
                                                                    Constantes.VALOR_CERO :
                                                                    this.cboCriterioNivelMaterial.SelectedValue.ToString();

            operacion.producto.nivelColor = new NivelColor();
            operacion.producto.nivelColor.codigo = this.cboCriterioNivelColor.SelectedValue.ToString().Equals(Constantes.CODIGO_SELECCIONE) ?
                                                                    Constantes.VALOR_CERO :
                                                                    this.cboCriterioNivelColor.SelectedValue.ToString();

            operacion.producto.codProductoProveedor = this.txtCriterioCodProductoProv.Text;
            operacion.producto.descripcion = this.txtDescripcionBusqueda.Text;
            operacion.producto.unionProducto = string.Empty;
            operacion.producto.estado = this.ESTADO;

            // Instanciando y ejecutando llamada al ServicioREST
            ConexionREST conexionREST = new ConexionREST();
            contenidoXML = conexionREST.ejecutarOperacion(operacion);

            // Obteniendo Objeto de Error
            OperacionError operacionError = contenidoXML.DeserializarTo<OperacionError>();

            // Validar si hay error
            if (operacionError != null)
            {
                Libreria.ShowMessageboxError(operacionError.descripcion);
                return;
            }

            // Obteniendo Objeto de ListaProducto
            ListaProducto listaProducto = contenidoXML.DeserializarTo<ListaProducto>();

            // Mostrar el total de registros encontrados
            this.lblTotalRegistros.Text = string.Format(FORMATO_TOTAL_ENCONTRADOS, listaProducto.lista.Count);

            // Se establece propiedad para evitar que genere nuevas columnas que no estan mapeadas en la grilla
            this.dgvListado.AutoGenerateColumns = false;

            // Se establece la fuente de datos de la grilla
            this.dgvListado.DataSource = listaProducto.lista;

            // Activando o desactivando boton Abrir
            this.tbtnAbrir.Enabled = listaProducto.lista.Count > 0;

            // Colorear grilla deacuerdo a criterios
            pintarGrilla();
        }

        private void buscar()
        {
            try
            {
                if (validarEntradaBusqueda()) { return; }

                // Listar productos con el criterio y el valor ingresado
                listarProductos();

                // Estableciendo focus
                this.btnBuscar.Focus();
            }
            catch (Exception ex)
            {
                log.Error(ex.Message, ex);
                Libreria.MensajeError(ex, TITULO);
            }
        }

        private void nuevo()
        {
            // Estableciendo estado de TagPage de Listado y datos
            this.tabPagListado.Enabled = false; 
            this.tabPagDatos.Enabled = true;

            // Mostrar la segunda pagina del TabControl
            this.tabControl.SelectedIndex = 1;

            this.grpDatos.Enabled = true;
            this.cboEstado.Enabled = false;

            // Estableciendo los estados de los botones
            cambiarEstadoBotones(Opcion.Nuevo);

            // Limpiar los datos del formulario
            limpiarTodo();

            this.tipoOperacion = OperacionMantenimiento.Nuevo;

            // Estableciendo focus control txtDescripcion
            this.txtDescripcion.Focus();
        }

        private void editar()
        {
            this.grpDatos.Enabled = true;
            this.cboEstado.Enabled = true;

            // Estableciendo los estados de los botones
            cambiarEstadoBotones(Opcion.Editar);

            this.tipoOperacion = OperacionMantenimiento.Editar;

            // Estableciendo focus control txtDescripcion
            this.txtDescripcion.Focus();
        }

        private void abrir()
        {
            // Estableciendo estado de TagPage de Listado y datos
            this.tabPagListado.Enabled = false; this.tabPagDatos.Enabled = true;

            // Mostrar la segunda pagina del TabControl
            this.tabControl.SelectedIndex = 1;

            // Estableciendo los estados de los botones
            cambiarEstadoBotones(Opcion.Abrir);

            // Valida si seleccione algun equipos
            if (this.dgvListado.CurrentRow != null && this.dgvListado.CurrentRow.Index > -1)
            {
                ListPersonalizada<Producto> listaProducto = (ListPersonalizada<Producto>)this.dgvListado.DataSource;
                this.productoActual = listaProducto[this.dgvListado.CurrentRow.Index];
                // Datos Basicos
                this.txtCodigoCD.Text = this.productoActual.codigo;
                this.txtDescripcion.Text = this.productoActual.descripcion;
                this.txtObservaciones.Text = this.productoActual.observaciones;
                this.txtPVMinimo.Text = this.productoActual.precioVentaMinimo.ToString(Constantes.FORMATO_DECIMAL);
                this.txtPVMaximo.Text = this.productoActual.precioVentaMaximo.ToString(Constantes.FORMATO_DECIMAL);
                this.cboEstado.Text = this.productoActual.estado;
                // Imagen
                //this.picImagen.Image = this.productoActual.imagen.base64ToImage();
                // Medidas
                this.txtAlto.Text = this.productoActual.alto.ToString(Constantes.FORMATO_DECIMAL);
                this.txtAncho.Text = this.productoActual.ancho.ToString(Constantes.FORMATO_DECIMAL);
                this.txtLargo.Text = this.productoActual.largo.ToString(Constantes.FORMATO_DECIMAL);
                this.txtUnidadMedida.Text = this.productoActual.unidadMedida;
                // Niveles
                this.cboNivelProducto.SelectedValue = this.productoActual.nivelProducto.codigo;
                this.cboNivelTipo.SelectedValue = this.productoActual.nivelTipo.codigo;
                this.cboNivelMaterial.SelectedValue = this.productoActual.nivelMaterial.codigo;
                this.cboNivelColor.SelectedValue = this.productoActual.nivelColor.codigo;
                // Proveedor
                this.proveedorActual = this.productoActual.proveedor;
                this.txtDesProveedor.Text = this.proveedorActual.razonSocial;
                this.txtCodProductoProv.Text = this.productoActual.codProductoProveedor;
                

                // Cargar imagen y componentes del producto
                abrir_ProductoyComponentes(this.productoActual.codigo);
            }
        }

        private void abrir_ProductoyComponentes(string codigoProducto)
        {
            Operacion operacion = null;
            string contenidoXML = string.Empty;

            // Estableciendo operacion a ser enviada al Servicio REST
            operacion = new Operacion();
            operacion.numero = Constantes.OPERACION_OBTENER_PRODUCTO;
            operacion.producto = new Producto { codigo = codigoProducto };
            operacion.tienda = new Tienda();
            operacion.tienda = ParametrosAplicacion.TIENDA_ACTUAL;

            // Instanciando y ejecutando llamada al ServicioREST
            ConexionREST conexionREST = new ConexionREST();
            contenidoXML = conexionREST.ejecutarOperacion(operacion);

            // Obteniendo Objeto de Error
            OperacionError operacionError = contenidoXML.DeserializarTo<OperacionError>();

            // Validar si hay error
            if (operacionError != null)
            {
                Libreria.ShowMessageboxError(operacionError.descripcion);
                return;
            }

            // Obteniendo Objeto de Producto
            Producto producto = contenidoXML.DeserializarTo<Producto>();

            // Se establece imagen del producto
            this.picImagen.Image = producto.imagen.base64ToImage();

            // Si tiene componentes
            this.chkComponentes.Checked = producto.componentes.Equals(Constantes.SI);

            //Si es un producto en consignacion
            this.chkConsignacion.Checked = producto.consignacion.Equals(Constantes.SI);

            this.chkUnionProducto.Checked = producto.unionProducto.Equals(Constantes.SI); 

            //Se cargan los componentes
            this.listaComponente = producto.listaComponente;

            this.productoActual = producto;

            // Se establece propiedad para evitar que genere nuevas columnas que no estan mapeadas en la grilla
            //this.dgvListadoComponentes.AutoGenerateColumns = false;

            // Se establece fuente de datos
            //this.dgvListadoComponentes.DataSource = producto.listaComponente.lista == null ?
            //                                        new ListPersonalizada<Componente>() :
            //                                        producto.listaComponente.lista;
        }

        private void cancelar()
        {
            if ( (this.tipoOperacion == OperacionMantenimiento.Editar) ||
                 (!this.grpDatos.Enabled))
            {
                this.cboCriterioNivelProducto.SelectedValue = Constantes.CODIGO_SELECCIONE;
                this.cboCriterioNivelTipo.SelectedValue = Constantes.CODIGO_SELECCIONE;
                this.cboCriterioNivelMaterial.SelectedValue = Constantes.CODIGO_SELECCIONE;
                this.cboCriterioNivelColor.SelectedValue = Constantes.CODIGO_SELECCIONE;

                this.txtCriterioCodProductoProv.Text = this.txtCodProductoProv.Text;

                // Refrescar grilla
                listarProductos();
            }

            // Estableciendo estado de TagPage de Listado y datos
            this.tabPagListado.Enabled = true; this.tabPagDatos.Enabled = false;

            // Mostrar la primera pagina del TabControl
            this.tabControl.SelectedIndex = 0;

            // Deshabilitando el grupoBox de datos
            this.grpDatos.Enabled = false;

            // Estableciendo los estados de los botones
            cambiarEstadoBotones(Opcion.Cancelar);

            // Estableciendo focus
            this.btnBuscar.Focus();
        }

        private void grabar()
        {
            Operacion operacion = null;
            string contenidoXML = string.Empty;

            try
            {
                if (validarEntrada()) { return; }

                // Solicitar confirmacion
                if (!Libreria.ShowMessageboxPregunta((this.tipoOperacion == OperacionMantenimiento.Nuevo ?
                                                                            "¿Estas seguro de registrar el producto?" :
                                                                            "¿Estas seguro de modificar el producto actual?"), TITULO)) { return; }


                // Estableciendo operacion a ser enviada al Servicio REST
                operacion = new Operacion();
                operacion.numero = this.tipoOperacion == OperacionMantenimiento.Nuevo ? Constantes.OPERACION_REGISTRAR_PRODUCTO : Constantes.OPERACION_MODIFICAR_PRODUCTO;

                operacion.producto = new Producto();
                operacion.producto.codigo = this.tipoOperacion == OperacionMantenimiento.Nuevo ? Constantes.VALOR_CERO : this.productoActual.codigo;
                operacion.producto.descripcion = this.txtDescripcion.Text;
                operacion.producto.precioVentaMinimo = Convert.ToDouble(this.txtPVMinimo.Text);
                operacion.producto.precioVentaMaximo = Convert.ToDouble(this.txtPVMaximo.Text);
                operacion.producto.observaciones = this.txtObservaciones.Text;

                // Estableciendo imagen en base64
                operacion.producto.imagen = this.picImagen.Image == null ? string.Empty : this.picImagen.Image.imageToBase64(ImageFormat.Jpeg);

                // Estableciendo y Instanciando nivel producto
                operacion.producto.nivelProducto = new NivelProducto();
                operacion.producto.nivelProducto.codigo = this.cboNivelProducto.SelectedValue.ToString();
                
                // Estableciendo y Instanciando nivel tipo
                operacion.producto.nivelTipo = new NivelTipo();
                operacion.producto.nivelTipo.codigo = this.cboNivelTipo.SelectedValue == null?
                                                      Constantes.VALOR_CERO: 
                                                      this.cboNivelTipo.SelectedValue.ToString();

                // Estableciendo y Instanciando nivel material
                operacion.producto.nivelMaterial = new NivelMaterial();
                operacion.producto.nivelMaterial.codigo = this.cboNivelMaterial.SelectedValue == null ?
                                                          Constantes.VALOR_CERO :
                                                          this.cboNivelMaterial.SelectedValue.ToString();

                // Estableciendo y Instanciando nivel color
                operacion.producto.nivelColor = new NivelColor();
                operacion.producto.nivelColor.codigo = this.cboNivelColor.SelectedValue == null?
                                                       Constantes.VALOR_CERO:
                                                       this.cboNivelColor.SelectedValue.ToString();

                // Estableciendo y Instanciando proveedor
                operacion.producto.proveedor = this.proveedorActual;
                operacion.producto.codProductoProveedor = this.txtCodProductoProv.Text;

                // Estableciendo medidas
                operacion.producto.alto = Convert.ToDouble(this.txtAlto.Text);
                operacion.producto.ancho = Convert.ToDouble(this.txtAncho.Text);
                operacion.producto.largo = Convert.ToDouble(this.txtLargo.Text);
                operacion.producto.unidadMedida = this.txtUnidadMedida.Text.Trim();

                // Estableciendo estado y fecharegistro
                operacion.producto.estado = this.cboEstado.SelectedValue.ToString();
                operacion.producto.fechaRegistro = DateTime.Now.ToString(Constantes.FORMATO_FECHAHORA);

                // Estableciendo listado de componentes
                //operacion.producto.listaComponente = new ListaComponente();
                //operacion.producto.listaComponente.lista = (ListPersonalizada<Componente>)this.dgvListadoComponentes.DataSource;
                operacion.producto.listaComponente = this.listaComponente;

                // Estableciendo si tiene o no componentes
                if (this.chkComponentes.Checked) {
                    operacion.producto.componentes = Constantes.SI;
                }
                else {
                    operacion.producto.componentes = Constantes.NO;
                }

                if (this.chkConsignacion.Checked)
                {
                    operacion.producto.consignacion = Constantes.SI;
                }
                else
                {
                    operacion.producto.consignacion = Constantes.NO;
                }

                if (this.chkUnionProducto.Checked)
                {
                    operacion.producto.unionProducto = Constantes.SI;
                }
                else
                {
                    operacion.producto.unionProducto = Constantes.NO;
                }

                // Instanciando y ejecutando llamada al ServicioREST
                ConexionREST conexionREST = new ConexionREST();
                contenidoXML = conexionREST.ejecutarOperacion(operacion);

                // Obteniendo Objeto de Error
                OperacionError operacionError = contenidoXML.DeserializarTo<OperacionError>();

                // Validar si hay error
                if (operacionError != null)
                {
                    Libreria.ShowMessageboxError(operacionError.descripcion);
                    return;
                }

                // Obteniendo resultado de ejecutar operacion
                OperacionResultado operacionResultado = contenidoXML.DeserializarTo<OperacionResultado>();

                string mensajeOK = this.tipoOperacion == OperacionMantenimiento.Nuevo ? "Registro guardado correctamente" : "Datos modificado correctamente";
                string mensajeError = this.tipoOperacion == OperacionMantenimiento.Nuevo ? "No se guardo los datos" : "No se actualizo los datos";


                if ((operacionResultado != null) &&
                    (operacionResultado.esOK.Equals(Constantes.SI)))
                {
                    // Mostrando codigo generado del producto
                    this.txtCodigoCD.Text = operacionResultado.codigoGenerado ?? this.txtCodigoCD.Text;
                    Libreria.ShowMessageboxInfo(mensajeOK, TITULO);
                }
                else
                {
                    Libreria.ShowMessageboxError(mensajeError, TITULO);
                    return;
                }

                this.grpDatos.Enabled = false;

                // Estableciendo los estados de los botones
                cambiarEstadoBotones(Opcion.Grabar);
            }
            catch (Exception ex)
            {
                log.Error(ex.Message, ex);
                Libreria.MensajeError(ex, TITULO);
            }
        }

        private void eliminar()
        {
            Operacion operacion = null;
            string contenidoXML = string.Empty;

            try
            {
                // Solicitar confirmacion para eliminar el producto
                if (!Libreria.ShowMessageboxPregunta("¿Esta seguro de eliminar a este Producto?", TITULO)) { return; }

                // Estableciendo operacion a ser enviada al Servicio REST
                operacion = new Operacion();
                operacion.numero = Constantes.OPERACION_ELIMINAR_PRODUCTO;

                operacion.producto = new Producto { codigo = this.productoActual.codigo };

                // Instanciando y ejecutando llamada al ServicioREST
                ConexionREST conexionREST = new ConexionREST();
                contenidoXML = conexionREST.ejecutarOperacion(operacion);

                // Obteniendo Objeto de Error
                OperacionError operacionError = contenidoXML.DeserializarTo<OperacionError>();

                // Validar si hay error
                if (operacionError != null)
                {
                    Libreria.ShowMessageboxError(operacionError.descripcion);
                    return;
                }

                // Obteniendo resultado de ejecutar operacion
                OperacionResultado operacionResultado = contenidoXML.DeserializarTo<OperacionResultado>();

                if ((operacionResultado != null) &&
                    (operacionResultado.esOK.Equals(Constantes.SI)))
                {
                    Libreria.ShowMessageboxInfo("Registro eliminado correctamente", TITULO);
                }
                else
                {
                    Libreria.ShowMessageboxError("No se elimino el Registro", TITULO);
                    return;
                }

                // Estableciendo estado de TagPage de Listado y datos
                this.tabPagListado.Enabled = true; this.tabPagDatos.Enabled = false;

                // Mostrar la primera pagina del TabControl
                this.tabControl.SelectedIndex = 0;

                this.grpDatos.Enabled = false;

                listarProductos();

                // Estableciendo los estados de los botones
                cambiarEstadoBotones(Opcion.Eliminar);
            }
            catch (Exception ex)
            {
                log.Error(ex.Message, ex);
                Libreria.MensajeError(ex, TITULO);
            }
        }

        private bool validarEntrada()
        {
            bool resultado = false;

            this.txtDescripcion.Text = this.txtDescripcion.Text.Trim();
            this.txtPVMinimo.Text = this.txtPVMinimo.Text.Trim();
            this.txtPVMaximo.Text = this.txtPVMaximo.Text.Trim();
            this.txtDesProveedor.Text = this.txtDesProveedor.Text.Trim();
            this.txtCodProductoProv.Text = this.txtCodProductoProv.Text.Trim();

            this.txtAlto.Text = this.txtAlto.Text.Trim();
            this.txtAncho.Text = this.txtAncho.Text.Trim();
            this.txtLargo.Text = this.txtLargo.Text.Trim();
            this.txtUnidadMedida.Text = this.txtUnidadMedida.Text.Trim();

            if (this.txtDescripcion.Text.Equals(string.Empty))
            {
                Libreria.CampoNecesario(this.txtDescripcion, "Debe ingresar el campo Descripción", TITULO);
                return true;
            }

            if (this.txtPVMinimo.Text.Equals(string.Empty))
            {
                Libreria.CampoNecesario(this.txtPVMinimo, "Debe ingresar el campo Precio Minimo", TITULO);
                return true;
            }

            if (this.txtPVMaximo.Text.Equals(string.Empty))
            {
                Libreria.CampoNecesario(this.txtPVMaximo, "Debe ingresar el campo Precio Máximo", TITULO);
                return true;
            }

            if (this.txtDesProveedor.Text.Equals(string.Empty))
            {
                Libreria.CampoNecesario(this.txtDesProveedor, "Debe ingresar el campo Proveedor", TITULO);
                return true;
            }

            

            return resultado;
        }

        private void cambiarEstadoBotones(Opcion tipoOpcion)
        {
            switch (tipoOpcion)
            {
                case Opcion.Abrir:
                    this.tbtnEditar.Enabled = true;
                    this.tbtnNuevo.Enabled = true;
                    this.tbtnEliminar.Enabled = true;
                    this.tbtnCancelar.Enabled = true;

                    this.tbtnAbrir.Enabled = false;
                    this.tbtnGrabar.Enabled = false;
                    break;
                case Opcion.Nuevo:
                    this.tbtnGrabar.Enabled = true;
                    this.tbtnCancelar.Enabled = true;

                    this.tbtnNuevo.Enabled = false;
                    this.tbtnAbrir.Enabled = false;
                    this.tbtnEditar.Enabled = false;
                    this.tbtnEliminar.Enabled = false;
                    break;
                case Opcion.Editar:
                    this.tbtnGrabar.Enabled = true;
                    this.tbtnCancelar.Enabled = true;

                    this.tbtnEditar.Enabled = false;
                    this.tbtnNuevo.Enabled = false;
                    this.tbtnEliminar.Enabled = false;
                    break;
                case Opcion.Grabar:
                    this.tbtnNuevo.Enabled = true;
                    this.tbtnEliminar.Enabled = true;
                    this.tbtnCancelar.Enabled = true;
                    this.tbtnEditar.Enabled = true;

                    this.tbtnGrabar.Enabled = false;
                    break;
                case Opcion.Cancelar:
                    //this.tbtnAbrir.Enabled = true;
                    this.tbtnNuevo.Enabled = true;

                    this.tbtnEliminar.Enabled = false;
                    this.tbtnCancelar.Enabled = false;
                    this.tbtnGrabar.Enabled = false;
                    this.tbtnEditar.Enabled = false;
                    break;
                case Opcion.Eliminar:
                    this.tbtnAbrir.Enabled = true;
                    this.tbtnNuevo.Enabled = true;

                    this.tbtnEliminar.Enabled = false;
                    this.tbtnCancelar.Enabled = false;
                    this.tbtnGrabar.Enabled = false;
                    this.tbtnEditar.Enabled = false;
                    break;
            }
        }

        private void limpiarTodo()
        {
            this.txtCodigoCD.Text = string.Empty;
            this.txtDescripcion.Text = string.Empty;
            this.txtObservaciones.Text = string.Empty;
            this.txtPVMinimo.Text = Constantes.VALOR_CERO;
            this.txtPVMaximo.Text = Constantes.VALOR_CERO;
            this.txtDesProveedor.Text = string.Empty;
            this.txtCodProductoProv.Text = string.Empty;
            this.txtAlto.Text = Constantes.VALOR_CERO;
            this.txtAncho.Text = Constantes.VALOR_CERO;
            this.txtLargo.Text = Constantes.VALOR_CERO;
            this.txtUnidadMedida.Text = Constantes.DESCRIPCION_UNIDAD;
            this.cboEstado.Text = Constantes.ESTADO_DESCRIPCION_ACTIVO;
            this.chkUnionProducto.Checked = false;
            this.chkConsignacion.Checked = false;
            this.chkComponentes.Checked = false;

            this.picImagen.Image = null;

            if (this.listaComponente != null)
            {
                this.listaComponente.clear();

                //// Se establece propiedad para evitar que genere nuevas columnas que no estan mapeadas en la grilla
                //this.dgvListadoComponentes.AutoGenerateColumns = false;

                //// Actualizando fuente de datos de la grilla
                //this.dgvListadoComponentes.DataSource = null;
                //this.dgvListadoComponentes.DataSource = listaComponente;
            }
        }

       

        private void buscarImagen()
        {
            OpenFileDialog dialog = new OpenFileDialog();
            dialog.Filter = FILTRO_VENTANA_EXAMINAR;
            dialog.InitialDirectory = RUTA_INICIAL;
            dialog.Title = TITULO_EXAMINAR_ARCHIVO_IMAGEN;

            if (dialog.ShowDialog() == DialogResult.Cancel) { return; }

            this.picImagen.ImageLocation = dialog.FileName;
        }

        private void seleccionNiveles()
        {
            string codigoNivelProducto = string.Empty;

            if (this.cboNivelProducto.SelectedValue is string)
            {
                codigoNivelProducto = this.cboNivelProducto.SelectedValue.ToString();
            }
            else
            {
                codigoNivelProducto = ((NivelProducto)this.cboNivelProducto.SelectedValue).codigo;
            }

            List<NivelTipo> listaNivelTipo = this.niveles.listaNivelTipo.lista;
            List<NivelMaterial> listaNivelMaterial = this.niveles.listaNivelMaterial.lista;
            List<NivelColor> listaNivelColor = this.niveles.listaNivelColor.lista;

            var listaTipo = from cust in listaNivelTipo
                            where cust.codNivelProducto == codigoNivelProducto
                            select cust;

            var listaMaterial = from cust in listaNivelMaterial
                                where cust.codNivelProducto == codigoNivelProducto
                                select cust;

            var listaColor = from cust in listaNivelColor
                             where cust.codNivelProducto == codigoNivelProducto
                             select cust;

            this.cboNivelTipo.DataSource = listaTipo.ToList<NivelTipo>();
            this.cboNivelTipo.ValueMember = Constantes.GENERAL_CODIGO;
            this.cboNivelTipo.DisplayMember = Constantes.GENERAL_DESCRIPCION;

            this.cboNivelMaterial.DataSource = listaMaterial.ToList<NivelMaterial>();
            this.cboNivelMaterial.ValueMember = Constantes.GENERAL_CODIGO;
            this.cboNivelMaterial.DisplayMember = Constantes.GENERAL_DESCRIPCION;

            this.cboNivelColor.DataSource = listaColor.ToList<NivelColor>();
            this.cboNivelColor.ValueMember = Constantes.GENERAL_CODIGO;
            this.cboNivelColor.DisplayMember = Constantes.GENERAL_DESCRIPCION;
        }

        private void seleccionNivelesBusqueda()
        {
            string codigoNivelProducto = string.Empty;

            if (this.cboNivelProducto.SelectedValue is string)
            {
                codigoNivelProducto = this.cboCriterioNivelProducto.SelectedValue.ToString();
            }
            else
            {
                codigoNivelProducto = ((NivelProducto)this.cboCriterioNivelProducto.SelectedValue).codigo;
            }

            List<NivelTipo> listaNivelTipo = this.niveles.listaNivelTipo.lista;
            List<NivelMaterial> listaNivelMaterial = this.niveles.listaNivelMaterial.lista;
            List<NivelColor> listaNivelColor = this.niveles.listaNivelColor.lista;

            List<NivelTipo> listaSeleccionNivelTipo = new List<NivelTipo>();
            listaSeleccionNivelTipo.Add(new NivelTipo { codigo = Constantes.CODIGO_SELECCIONE, descripcion = Constantes.DESCRIPCION_SELECCIONE });

            List<NivelMaterial> listaSeleccionNivelMaterial = new List<NivelMaterial>();
            listaSeleccionNivelMaterial.Add(new NivelMaterial { codigo = Constantes.CODIGO_SELECCIONE, descripcion = Constantes.DESCRIPCION_SELECCIONE });

            List<NivelColor> listaSeleccionNivelColor = new List<NivelColor>();
            listaSeleccionNivelColor.Add(new NivelColor { codigo = Constantes.CODIGO_SELECCIONE, descripcion = Constantes.DESCRIPCION_SELECCIONE });

            var listaTipo = (from item in listaSeleccionNivelTipo
                            select item).
                            Union
                            (from itemTipo in listaNivelTipo
                            where itemTipo.codNivelProducto == codigoNivelProducto
                            select itemTipo);

            var listaMaterial = (from item in listaSeleccionNivelMaterial
                                select item).
                                Union
                                (from itemMaterial in listaNivelMaterial
                                where itemMaterial.codNivelProducto == codigoNivelProducto
                                select itemMaterial);

            var listaColor = (from item in listaSeleccionNivelColor
                             select item).
                             Union
                             (from itemColor in listaNivelColor
                             where itemColor.codNivelProducto == codigoNivelProducto
                             select itemColor);

            this.cboCriterioNivelTipo.DataSource = listaTipo.ToList<NivelTipo>();
            this.cboCriterioNivelTipo.ValueMember = Constantes.GENERAL_CODIGO;
            this.cboCriterioNivelTipo.DisplayMember = Constantes.GENERAL_DESCRIPCION;

            this.cboCriterioNivelMaterial.DataSource = listaMaterial.ToList<NivelMaterial>();
            this.cboCriterioNivelMaterial.ValueMember = Constantes.GENERAL_CODIGO;
            this.cboCriterioNivelMaterial.DisplayMember = Constantes.GENERAL_DESCRIPCION;

            this.cboCriterioNivelColor.DataSource = listaColor.ToList<NivelColor>();
            this.cboCriterioNivelColor.ValueMember = Constantes.GENERAL_CODIGO;
            this.cboCriterioNivelColor.DisplayMember = Constantes.GENERAL_DESCRIPCION;
        }

        private void elegirProveedor()
        {
            using (frmMantProveedor frmMantProveedor = new frmMantProveedor())
            {
                frmMantProveedor.formularioBusqueda = true;
                if (frmMantProveedor.ShowDialog() == DialogResult.Cancel) { return; }

                this.proveedorActual = frmMantProveedor.proveedorActual;
                this.txtDesProveedor.Text = this.proveedorActual.razonSocial;
            }
        }

        private void seleccionarProducto()
        {
            if (this.formularioBusqueda)
            {
                // Valida si seleccione algun producto
                if (this.dgvListado.CurrentRow != null && this.dgvListado.CurrentRow.Index > -1)
                {
                    ListPersonalizada<Producto> listaProducto = (ListPersonalizada<Producto>)this.dgvListado.DataSource;
                    this.productoActual = listaProducto[this.dgvListado.CurrentRow.Index];

                    this.DialogResult = DialogResult.OK;
                }
            }
        }

        private void controlBotonesPorRol()
        {
            if (ParametrosAplicacion.ROL_ADMINISTRADOR.codigo.Equals(ParametrosAplicacion.USUARIO_ACTUAL.rol.codigo)) { return; }

            this.tbtnNuevo.Visible = false;
            this.tbtnEditar.Visible = false;
            this.tbtnEliminar.Visible = false;
            this.tbtnGrabar.Visible = false;

            this.ESTADO = Constantes.ESTADO_CODIGO_ACTIVO;
        }

        private void salir()
        {
            if (this.formularioBusqueda)
            {
                this.DialogResult = DialogResult.Cancel;
            }
            else
            {
                this.Close();
            }
        }

        private void abrirComponentes()
        {
            //Abrir la pantalla para agregar componentes
            try
            {
                using (frmMantComponenteProducto frmMantComponenteProducto = new frmMantComponenteProducto())
                {
                    // Validar si se cancelo operacion
                    frmMantComponenteProducto.listaComponente = this.listaComponente;
                    if (frmMantComponenteProducto.ShowDialog() == DialogResult.Cancel) 
                    { 
                        return; 
                    }
                    //En el retorno se debe obtener los datos de la lista de componentes
                    
                    this.listaComponente = frmMantComponenteProducto.listaComponente;
                    this.chkComponentes.Checked = frmMantComponenteProducto.Componentes;
                    this.chkUnionProducto.Checked = frmMantComponenteProducto.UnionProducto;
                    frmMantComponenteProducto.Dispose();
                }

            }
            catch (Exception ex)
            {
                log.Error(ex.Message, ex);
                Libreria.MensajeError(ex, TITULO);
            }
            

            //
        }
        #endregion

        private void cboCriterioNivelMaterial_SelectedIndexChanged(object sender, EventArgs e)
        {

        }








    }
}
